/*
 * Copyright 2024 ywcai
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

`include "defines.v"
`timescale 1ns/1ps

module id_ex(
	input	wire				clk,
	input	wire				rst_n,

    input   wire                stall_ex_req_i,
	input	wire				flush_ex_req_i,
	input	wire[`MemAddrBus]	pc_i,
	input	wire[`InstDataBus]	inst_i,
	input	wire				i_inst_auipc_i,
	input	wire    			mux_alu_src1_i,
	input	wire				mux_alu_src2_i,
	input	wire[3:0]			mux_alu_ctrl_i,
    input   wire[3:0]           mux_mul_ctrl_i,
	input	wire				mem_req_i,
	input	wire				mem_we_i,
	input	wire				mux_branch_i,
	input	wire[2:0]			mux_result_src_i,
	input	wire				mux_jump_i,
	input	wire				mux_pctarget_src_i,
	input	wire				mux_loadtype_i,
	input	wire				mux_storetype_i,
	input	wire[`RegAddrBus]	rs1_addr_i,
	input	wire[`RegDataBus]	rs1_data_i,
	input	wire[`RegAddrBus]	rs2_addr_i,
	input	wire[`RegDataBus]	rs2_data_i,
	input	wire				regwrite_en_i,
	input	wire[`RegAddrBus]	regwrite_addr_i,
	input	wire[`RegDataBus]	rs1_imm_value_i,
	input	wire[`RegDataBus]	rs2_imm_value_i,
	input	wire				w_suffix_i,
	input	wire[`TrapBus]		trap_code_i,

	output	reg[`MemAddrBus]	pc_o,
	output	reg[`InstDataBus]	inst_o,
	output	reg					i_inst_auipc_o,
	output	reg     			mux_alu_src1_o,
	output	reg					mux_alu_src2_o,
	output	reg[3:0]			mux_alu_ctrl_o,
    output  reg[3:0]            mux_mul_ctrl_o,
	output	reg					mem_req_o,
	output	reg					mem_we_o,
	output	reg					mux_branch_o,
	output	reg					regwrite_en_o,
	output	reg[2:0]			mux_result_src_o,
	output	reg					mux_jump_o,
	output	reg					mux_pctarget_src_o,
	output	reg					mux_loadtype_o,
	output	reg					mux_storetype_o,
	output	reg[`RegAddrBus]	rs1_addr_o,
	output	reg[`RegDataBus]	rs1_data_o,
	output	reg[`RegAddrBus]	rs2_addr_o,
	output	reg[`RegDataBus]	rs2_data_o,
    output  reg[`RegAddrBus]    regwrite_addr_o,
	output	reg[`RegDataBus]	rs1_imm_value_o,
	output	reg[`RegDataBus]	rs2_imm_value_o,
	output	reg					w_suffix_o,
	output	reg[`TrapBus]		trap_code_o
	);

	always @(posedge clk) begin
		if (rst_n == `RESET_ENABLE || flush_ex_req_i) begin
			pc_o <= `ZERO_ADDR;
			inst_o <= `INST_NOP;
			i_inst_auipc_o <= `DISABLE;
			mux_alu_src1_o <= `DISABLE;
			mux_alu_src2_o <= `DISABLE;
			mux_alu_ctrl_o <= 4'b0000;
            mux_mul_ctrl_o <= 4'b0000;
			mem_req_o <= `DISABLE;
			mem_we_o <= `DISABLE;
			mux_branch_o <= `DISABLE;
 			regwrite_en_o <= `DISABLE;
			mux_result_src_o <= 3'b000;
			mux_jump_o <= `DISABLE;
			mux_pctarget_src_o <= `DISABLE;
			mux_loadtype_o <= `DISABLE;
			mux_storetype_o <= `DISABLE;
			rs1_addr_o <= `REG_ZERO_ADDR;
			rs1_data_o <= `ZERO;
			rs2_addr_o <= `REG_ZERO_ADDR;
			rs2_data_o <= `ZERO;
			regwrite_addr_o <= 5'h0;
			rs1_imm_value_o <= `ZERO;
			rs2_imm_value_o <= `ZERO;
			w_suffix_o <= `DISABLE;
			trap_code_o <= `TRAP_NONE;
		end else if(!stall_ex_req_i) begin
			pc_o <= pc_i;
			inst_o <= inst_i;
			i_inst_auipc_o <= i_inst_auipc_i;
			mux_alu_src1_o <= mux_alu_src1_i;
			mux_alu_src2_o <= mux_alu_src2_i;
			mux_alu_ctrl_o <= mux_alu_ctrl_i;
            mux_mul_ctrl_o <= mux_mul_ctrl_i;
			mem_req_o <= mem_req_i;
			mem_we_o <= mem_we_i;
			mux_branch_o <= mux_branch_i;
			regwrite_en_o <= regwrite_en_i;
			mux_result_src_o <= mux_result_src_i;
			mux_jump_o <= mux_jump_i;
			mux_pctarget_src_o <= mux_pctarget_src_i;
			mux_loadtype_o <= mux_loadtype_i;
			mux_storetype_o <= mux_storetype_i;
			rs1_addr_o <= rs1_addr_i;
			rs1_data_o <= rs1_data_i;
			rs2_addr_o <= rs2_addr_i;
			rs2_data_o <= rs2_data_i;
			regwrite_addr_o <= regwrite_addr_i;
			rs1_imm_value_o <= rs1_imm_value_i;
			rs2_imm_value_o <= rs2_imm_value_i;
			w_suffix_o <= w_suffix_i;
			trap_code_o <= trap_code_i;
		end
    end

endmodule
